PHP Routing
Home

PHP Routing

PHP Routing

In een normale PHP toepassing moet elke URL overeenkomen met een specifiek php-bestand. Een URL http: //domain/mijnpagina.php moet bijvoorbeeld overeenkomen met het bestand mijnpagina.php dat de html, inhoud en PHP code bevat voor het weergeven van de gevraagde pagina in de browser.

We gaan routing introduceren zodat we niet aan elke URL een php-bestand moeten koppelen. Met routing kunnen we een ​​URL-patroon definiëren voor de request handler (verzoekbehandelaar). Deze request handler zal overeenomen met een klasse in een bepaald bestand, namelijk de controllerklasse en de actiemethode. Bijvoorbeeld http://domein/student/readAll verwijst naar de readAll methode van de Student klasse.

Een route configureren

Een route definieert het URL-patroon en de handler-informatie. De volgende afbeelding illustreert het routeringsproces:

MVC routing
MVC routing

Route patroon

Het URL-patroon begint na het domeinnaamgedeelte in de URL. Het URL-patroon {controller}/{action}/{id} ziet er bijvoorbeeld uit als:

localhost:63343/{controller/{action}/{id}

Alles na localhost:63343/ wordt beschouwd als de naam van de controller. Alles na de naam van de controller wordt beschouwd als de actienaam (methode) en wat daarna komt wordt beschouwd als de waarde van id-parameter.

MVC URL Pattern
MVC URL Pattern

Als de URL na de domeinnaam niets bevat, zullen de standaardcontroller en actiemethode de aanvraag verwerken. Bijvoorbeeld: http://localhost:63343/ wordt afgehandeld door HomeController en Index-methode.

In de volgende tabel wordt weergegeven welke controller, actiemethode en id-parameter verschillende URL's zullen aanspreken:

URL Controller Action Id
http://localhost:63343/home HomeController Index null
http://localhost:63343/home/index/123 HomeController Index 123
http://localhost:63343/home/about HomeController About null
http://localhost:63343/home/contact HomeController Contact null
http://localhost:63343/student StudentController Index null
http://localhost:63343/student/edit/123 StudentController Edit 123

Alle requests omleiden naar index.php

Vermits de URL niet meer naar een PHP-pagina verwijst maar naar een controller en een methode moeten we telkens wanneer de webserver een request ontvangt, een stukje PHP code uitvoeren die de overeenkomstige controller klasse instantiëert en de respectievelijke methode uitvoert. Deze code stoppen we in een bestand met de naam index.php. En dat bestaat staat in de root van de website.

Deze index.php in de root van onze website is het punt waar alle request naar toe gestuurd worden. Dus moeten we ervoor zorgen dat alle trafiek omgeleid wordt naar deze index.php pagina.

  1. In de root van de website maak je een .htaccess bestand die alle aanvragen omleidt naar index.php:
  2. RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.+)$ index.php [QSA,L]
  3. Als je lokaal werkt met de ingebouwde webserver:
    1. Om alle requests naar de index.php pagina om te leiden maak je bv. een local.php in de webroot met daarin:
      if (file_exists(__DIR__ . '/' . $_SERVER['REQUEST_URI'])) { 
         return false; // serve the requested resource as-is. 
      } else { 
         include_once 'index.php';
      }
      
    2. Visual Code: open de terminal (ook in de terminal van PHPStorm) en typ: php -S localhost:63344 local.php:
      start built-in PHP webserver with routing in stead of htaccess
      start built-in PHP webserver with routing in stead of htaccess
    3. meer info hierover:
      1. Lorna Jane, PHP 5.4 Built In Webserver, 30/12/2010
      2. PHP built in server and .htaccess mod rewrite
    4. PHPStorm: je kan de router script opgeven in PHPStorm. Open Edit Configuration:
      PHPStorm use router script
      PHPStorm use router script
  4. We kunnen het gevolg van de instellingen bekijken door gebruik te maken van de PHP $_SERVER globale variabele. In de mvc-routing-index.php pagina voeg je de volgende PHP code toe:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charsetUTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>MVC routing in PHP</title>
    </head>
    <body>
       <pre>
            <?php
                var_dump($_SERVER);
            ?>
       </pre>
    </body>
    </html>	
  5. Start de built-in PHP webserver met php -S localhost:63344 local.php.
    1. typ je een url in gevolgd door een schuine streep /:
      http://localhost:63344/, dan vind je: ["REQUEST_URI"]=> string(1) "/".
    2. typ je dezelfde url in gevolgd door een schuine streep en een de naam van een controller: http://localhost:63344/student krijg je:
      ["REQUEST_URI"]=> string(8) "/student"
      
    3. typ je dezelfde url in gevolgd door een schuine streep en een de naam van een controller gevolgd door de naam van de actiemethode en een id:
      ttp://localhost:63344/student/read/100 krijg je :
      ["REQUEST_URI"]=> string(17) "/student/read/100"
      

Routing

Met deze kennis gaan we nu een router methode maken. De methode moet op basis van de gegevens in de uri de naam van de controllerklasse, actiemethode en parameter in een associatieve array retourneren.

  1. als ["REQUEST_URI"] leeg is, is de controllernaam standaard Home en de methodenaam index
  2. het eerste deel van de REQUEST_URI is de controllernaam;
  3. het tweede deel is de methodenaam, is er geen tweede deel dan is de methodenaam index;
  4. het derde deel is de parameter, is er geen derde deel dan is er ook geen parameter
  5. de functie retourneert een associatieve array met de naam van de controller en de methode en de waarde van de optionele parameter.
  6. We maken een functie met de naam getRouting die de route analyseert. We initialiseren de controllernaam standaard op Home en de actiemethode op index.
  7. De klasse met de naam de FrontController, die opgeroepen wordt net vooraleer de Controller klasse gebruikt zal worden, plaatsen we in het bestand met de naam fric-frac-simple-crud\vendor\threepennymvc. We zetten die in een map die naast de public map staat omdat de gebruiker daar geen toegang toe geeft.
  8. De splitUri methode in een statische methode. Het is niet bedoeling van instanties van die klasse te maken vermits we er nooit meer dan 1 van nodig zullen hebben. We gebruiken hier alleen OO om onze code te ordenen.
  9. De naam van de namespace is ThreepennyMVC. Dat is de 'commerciële' naam die we eraan geven.
  10. Hier is de code:
    <?php
    /**
     * Created by ModernWays
     * User: Jef Inghelbrecht
     * Date: 23/02/2020
     * Time: 10:32
     */
    
    namespace ThreepennyMVC;
    
    class FrontController
    {
        public static function splitUri($uri, $namespaceName = '\\',
            $controllerName = 'Home', $actionMethodName = 'index')
        {
            $controllerClassName =  "{$namespaceName}\\Controllers\\{$controllerName}Controller";
             $parameterValue = -1;
            $delimiter = '/';
            // remove last \ if present
            $namespaceName = rtrim($namespaceName, '\\');
            // remove first /, if present
            $uri = ltrim($uri, $delimiter);
            // make sure there is always a last /
            $uri = $uri . $delimiter;
            // remove last /, if present
            // $uri = rtrim($uri, $delimiter);
             $pos1 = strpos($uri, $delimiter);
            if ($pos1 > 0) {
                 // klassenamen in PHP beginnen met een hoofdletter, pascalnotatie
                $controllerClassName = $namespaceName . '\\Controllers\\' .
                    ucfirst(substr($uri, 0, $pos1)) . 'Controller';
                $pos2 = strpos($uri, $delimiter, $pos1 + 1);
                // echo 'pos2: ' . $pos2 . 'pos 1' . $pos1;
                if ($pos2 > 0) {
                    // functies in camelcase notatie
                    // echo $uri;
                    $actionMethodName = lcfirst(substr($uri, $pos1 + 1, $pos2 - $pos1 - 1));
                    // echo self::$actionMethodName;
                    if ($pos2 < strlen($uri)) {
                        //echo 'pos3: ' . $pos3;
                        $pos3 = strpos($uri, $delimiter, $pos2);
                        if ($pos3 > 0) {
                            $parameterValue = rtrim(substr($uri, $pos3 + 1), '/');
                        }
                        if (empty($parameterValue)) {
                            $parameterValue = -1;
                        }
                    }
                }
             }
            return array(
                'controllerClassName' => $controllerClassName,
                'actionMethodName' => $actionMethodName,
                'parameterValue' => $parameterValue);
        }
    }
  11. We roepen de splitUri functie op in public/index.php en geven we de route als parameter mee, evenals de naam van de namespace waarin de controller staat, de naam van de standaardcontrollernaam en de naam van de standaardactiemethode:
    ?php
    // var_dump($_SERVER);
    use ThreepennyMVC\FrontController;
    include_once('../vendor/threepennymvc/FrontController.php');
    // default namespace is root \
    // otherwise specify it as argument
    $route = FrontController::splitUri($_SERVER['REQUEST_URI'], 'Fricfrac', 'Admin', 'index');
    ?>
    <!DOCTYPE html>
    <html lang="nl">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Fric-frac events</title>
    </head>
    
    <body>
        <h1>Route</h1>
        <pre>
        <?php var_dump($route); ?>
        </pre>
        <h1>Server</h1>
        <pre>
        <?php var_dump($_SERVER); ?>
        </pre>
    </body>
    
    </html>
  12. Open de terminal en ga naar de public map.
  13. Start de webbrower met:
    php -S localhost:63346 local.php
  14. En dat is het resultaat:
    Routing in PHP
    Routing in PHP

    Let erop dat de methode de eerste letter van Index naar een kleine letter omzet. Dat is omdat het de afspraak is om methoden in PHP in camelcase te schrijven.

Vergeet niet het .htaccess bestand te hernoemen of te verwijderen als je oefeningen van in de vorige lessen wilt uitproberen!

Bronnen

  1. Tania Rascia, The Simplest PHP Router, June 21st, 2018
  2. Routing in ASP.NET MVC

JI
2020-04-01 16:19:39